package com.cha.chaApp.sys.user.service.impl;

import com.cha.chaCommon.core.entity.User;
import com.cha.chaCommon.core.exception.CustomerException;
import com.cha.chaCommon.core.utils.JwtUtils;
import com.cha.chaCommon.redis.enums.RedisKeyEnums;
import com.cha.chaCommon.redis.utils.RedisUtils;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cha.chaApp.sys.user.dao.UserDao;
import com.cha.chaApp.sys.user.param.LoginParam;
import com.cha.chaApp.sys.user.param.RegisterParam;
import com.cha.chaApp.sys.user.service.UserService;
import com.cha.chaCommon.sms.enums.SmsEnum;
import com.cha.chaCommon.sms.utils.AliSmsUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.concurrent.ThreadPoolExecutor;

/*
@Author  hkf
@date 2024/11/8
--轻舟已过万重山--
*/
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao userDao;
    @Resource
    private ThreadPoolExecutor threadPoolExecutor;
    @Override
    public String login(LoginParam param) {
        User user = userDao.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhoneNumber, param.getPhone()));
        if(user == null){
            throw new CustomerException("用户不存在");
        }
        String md5 = SecureUtil.md5(param.getPassword());
        if(! md5.equals(user.getPassword())){
            throw new CustomerException("密码错误");
        }

        HashMap<String, Object> map = new HashMap<>();
        //map中存的是用户id,因为载荷可以解析,所以最好不要存密码
        map.put("uid",user.getUserId());
        //将map集合当成JWT的载荷存储,生成token
        String token = JwtUtils.createJwt(map);
        System.out.println("token:"+token);
        return token;
    }

    @Override
    public void register(RegisterParam param) {

        //从枚举类获取key
        String keyCode = String.format(param.getPhone());
        String code = (String) RedisUtils.getValue(keyCode);
        if(! param.getCode().equals(code)){
            throw new CustomerException("验证码错误");
        }
        User user = new User();
        BeanUtils.copyProperties(param,user);
        user.setName(param.getPhone());
        user.setPhoneNumber(param.getPhone());
        String md5 = SecureUtil.md5(param.getPassword());
        user.setPassword(md5);
        userDao.insert(user);
    }

    @Override
    public String getCode(String phone) {

        //验证手机号是否合法,使用正则表达式
        if(!phone.matches("^1[4-9]\\d{9}$")){
            throw new CustomerException("手机号不合法");
        }

        //hutool生成验证码
        String code = RandomUtil.randomNumbers(5);

        //从枚举类获取key
        String keyCode = String.format(RedisKeyEnums.CODE_KEY.getKey(),phone);
        String keyCodeNum = String.format(RedisKeyEnums.KEY_CODE_NUM.getKey(),phone);
        //判断验证码生成次数,redis中value存次数,键存"code:number:"+phone
        if(RedisUtils.hasKey(keyCode)){
            //如果有对应的键,则次数自增1
            RedisUtils.incrValue(keyCode,1L);
            //如果值大于三次,则抛出异常
            if((Integer) RedisUtils.getValue(keyCodeNum)>3){
                throw new CustomerException("十分钟内最多请求三次!请稍后再试....");
            }
        }else {
            //没有对应的键,创建一个键,次数设置为1
            RedisUtils.setValueTimeout(keyCodeNum,1,600);
        }
        //将验证码存储到redis中
        RedisUtils.setValueTimeout(phone,code,10*60);
        //异步发送验证码
        threadPoolExecutor.execute(() ->
                AliSmsUtils.sendSms(
                        SmsEnum.SMS_CODE.getSignName(),
                        SmsEnum.SMS_CODE.getTemplateCode(),
                        phone,code)
        );
        return code;

    }
}
